package com.bjpowernode.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.bjpowernode.constant.Constant;
import com.bjpowernode.entity.TPermission;
import com.bjpowernode.entity.TRole;
import com.bjpowernode.entity.TUser;
import com.bjpowernode.mapper.TPermissionMapper;
import com.bjpowernode.mapper.TRoleMapper;
import com.bjpowernode.mapper.TUserMapper;
import com.bjpowernode.query.BaseQuery;
import com.bjpowernode.query.UserQuery;
import com.bjpowernode.service.UserService;
import com.bjpowernode.util.LoginInfoUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * 用户服务实现类
 * 实现UserService接口，处理用户相关的业务逻辑
 * 使用@Service注解将该类注册为Spring容器中的Bean，以便进行依赖注入
 */
@Service
public class UserServiceImpl implements UserService {
    /**
     * 用户数据访问对象
     * 用于与数据库交互，执行用户相关的CRUD操作
     */
    @Resource
    private TUserMapper tUserMapper;
    /**
     * 权限数据访问对象
     * 用于与数据库交互，执行权限相关的CRUD操作
     */
    @Resource
    private TPermissionMapper tPermissionMapper;
    /**
     * 角色数据访问对象
     * 用于与数据库交互，执行角色相关的CRUD操作
     */
    @Resource
    private TRoleMapper tRoleMapper;
    /**
     * 密码编码器
     * 用于对用户密码进行加密存储和验证
     */
    @Resource
    private PasswordEncoder passwordEncoder;

    /**
     * 该方法在spring security框架登录的时候被调用
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //查询数据库，查询页面上传过来的这个用户名是否在数据库中存在，也就是根据该username查询用户对象
        TUser tUser = tUserMapper.selectByLoginAct(username);
        if (tUser == null) {
            throw new UsernameNotFoundException("登录账号不存在");
        }

        // 根据用户ID查询该用户拥有的角色列表
        List<TRole> tRoles = tRoleMapper.selectByUserId(tUser.getId());
        // 将查询到的角色列表设置到用户对象中
        tUser.setTRoleList(tRoles);
        //查询该用户的权限code列表（一个用户可能有多个权限code）
        List<TPermission> tPermissionList = tPermissionMapper.selectByUserId(tUser.getId());
        //把查询出来的角色放入用户对象中
        tUser.setTPermissionList(tPermissionList);

        //返回该用户对象
        return tUser;
    }

    /**
     * 根据页码获取用户分页数据
     *
     * @param current 当前页码，从1开始计数
     * @return PageInfo<TUser> 包含用户列表及分页信息的对象
     * @see PageHelper 分页插件，用于拦截查询并添加 LIMIT 子句
     * @see Constant#PAGE_SIZE 系统常量类中定义的每页记录数
     */
    @Override
    public PageInfo<TUser> getUserByPage(Integer current) {
        // 1. 初始化分页参数：当前页码和每页记录数
        // PageHelper会自动将下一条SQL查询转换为分页查询
        PageHelper.startPage(current, Constant.PAGE_SIZE);

        // 2. 调用Mapper层方法查询用户数据
        // 实际执行的SQL会自动添加 LIMIT 子句，如: SELECT * FROM t_user LIMIT (current-1)*PAGE_SIZE, PAGE_SIZE
        List<TUser> tUserList = tUserMapper.selectByPage(new BaseQuery());

        // 3. 将查询结果封装到PageInfo对象
        // PageInfo包含完整的分页信息：总记录数、总页数、当前页数据等
        PageInfo<TUser> page = new PageInfo<>(tUserList);

        // 4. 返回分页信息对象
        return page;
    }

    /**
     * 根据用户ID查询用户信息
     *
     * @param id 用户ID，不能为空
     * @return 对应的用户实体对象，若不存在则返回null
     * @see com.bjpowernode.mapper.TUserMapper#getUserById(Integer) 数据访问层查询方法
     */
    @Override
    public TUser getUserById(Integer id) {
        return tUserMapper.getUserById(id);
    }

    /**
     * 添加新用户
     *
     * @param userQuery 用户查询对象，包含用户注册信息
     * @return 影响的行数，1表示成功，0表示失败
     * @throws NullPointerException 当userQuery为null或必要字段缺失时抛出
     * @see com.bjpowernode.util.BeanUtil#copyProperties(Object, Object) 对象属性拷贝工具类
     * @see org.springframework.security.crypto.password.PasswordEncoder#encode(CharSequence) 密码加密方法
     */
    @Override
    public int addUser(UserQuery userQuery) {
        TUser tUser = new TUser();

        // 将查询对象属性拷贝到实体对象
        BeanUtil.copyProperties(userQuery, tUser);

        // 对密码进行加密处理
        String encode = passwordEncoder.encode(userQuery.getLoginPwd());

        tUser.setLoginPwd(encode);
        tUser.setCreateTime(new Date());
        // 设置创建者为当前登录用户ID
        tUser.setCreateBy(LoginInfoUtil.getCurrentLoginUser().getId());

        // 插入用户记录并返回影响行数
        int count = tUserMapper.insertSelective(tUser);

        return count;
    }

    /**
     * 更新用户信息
     *
     * @param userQuery 用户查询对象，包含待更新的用户信息
     * @return 影响的行数，1表示成功，0表示失败
     * @throws NullPointerException 当userQuery为null或id字段缺失时抛出
     * @see com.bjpowernode.util.BeanUtil#copyProperties(Object, Object) 对象属性拷贝工具类
     * @see org.springframework.security.crypto.password.PasswordEncoder#encode(CharSequence) 密码加密方法
     * @see com.bjpowernode.util.LoginInfoUtil#getCurrentLoginUser() 当前登录用户信息工具类
     */
    @Override
    public int editUser(UserQuery userQuery) {
        TUser tUser = new TUser();

        // 将查询对象属性拷贝到实体对象
        BeanUtil.copyProperties(userQuery, tUser);

        // 对密码进行加密处理（仅当密码不为空时）
        if (StringUtils.hasText(userQuery.getLoginPwd())) {
            tUser.setLoginPwd(passwordEncoder.encode(userQuery.getLoginPwd()));
        }

        tUser.setEditTime(new Date());
        // 设置修改者为当前登录用户ID
        tUser.setEditBy(LoginInfoUtil.getCurrentLoginUser().getId());

        // 更新用户记录并返回影响行数
        int count = tUserMapper.updateByPrimaryKeySelective(tUser);

        return count;
    }

    /**
     * 根据用户ID删除用户信息
     *
     * @param id 用户唯一标识符
     * @return int 影响的行数，1表示删除成功，0表示删除失败或用户不存在
     * @see TUserMapper#deleteByPrimaryKey(Integer) Mapper层删除用户的方法
     */
    @Override
    public int deleteUser(Integer id) {
        return tUserMapper.deleteByPrimaryKey(id);
    }

    /**
     * 批量删除用户
     * 实现UserService接口中的deleteUsers方法
     *
     * @param list 用户ID列表
     * @return 实际删除的用户数量
     */
    @Override
    public int deleteUsers(List<String> list) {
        // 调用数据访问层接口批量删除用户
        // 将用户ID列表传递给mapper层进行数据库操作
        return tUserMapper.deleteUsers(list);
    }

    @Override
    public List<TUser> getOwners() {
        return tUserMapper.selectOwners();
    }
}
